<?php


namespace app\admin\controller;


use app\admin\service\RbacService;
use app\common\exception\ParameterFailedException;
use app\common\validate\RCBCValidate;
use app\common\controller\CommonController;
use app\common\exception\NotFoundException;
use app\common\exception\RuntimeException;
use app\common\model\GroupModel;
use app\common\model\GroupRoleModel;
use app\common\model\RoleModel;
use app\common\model\UserModel;
use app\common\service\WarmUpCache;
use app\common\service\Lang;
use think\facade\Db;

class RbacController extends CommonController
{
    public function getRbacGroupList()
    {

        $result      = (new GroupModel())->with(['roles'])->order('index', 'desc')->select();
        foreach ($result as &$item) {
            $item->hidden([
                'roles.app',
                'roles.controller',
                'roles.action',
                'roles.method',
                'roles.pivot',
                'roles.delete_time',
                'delete_time',
            ]);
            $roleIds         = [];
            $groupRolesArray = $item->roles->toArray();
            foreach ($groupRolesArray as $role) {
                $roleIds[] = $role['id'];
            }
            $item['role_ids'] = $roleIds;
        }

        //return retJson(Lang::GETDone, RbacService::getRBACGroup());
        return retJson(Lang::GETDone, $result->toArray());
    }

    /**
     * @return \think\response\Json
     * @throws \Exception
     *
     * @Author: Li Guo Xin <guoxinlee129@gmail.com>
     * @Date: 2020/8/14
     * @Time: 17:28
     */
    public function postRBACGroup()
    {

        $params      = self::getParam([
            'group_name',
            'role_ids',
        ]);
        (new RCBCValidate())->goCheck(__FUNCTION__, $params);
        $ids = explode(',', $params['role_ids']);
        $ids = array_filter($ids);
        Db::startTrans();
        try {
            //有id
            if ($params['role_ids']) {
                //检查所有的roleid是否有效
                $roleCount = RoleModel::whereIn('id', $ids)->count();
                if ($roleCount !== count($ids)) {
                    throw new ParameterFailedException(['role_ids参数有误']);
                }
            }

            $oldGroupModel = (new GroupModel())->where('name', $params['group_name'])->find();
            if ($oldGroupModel) {
                throw new ParameterFailedException(['已存在相关的用户组名称']);
            }

            $groupModel       = new GroupModel();
            $groupModel->name = $params['group_name'];
            $groupModel->save();

            if ($ids) {
                $prepareGroupRoleData = [];
                foreach ($ids as $roleId) {
                    $prepareGroupRoleData[] = [
                        'group_id' => $groupModel->id,
                        'role_id'  => $roleId,
                    ];
                }
                (new GroupRoleModel())->saveAll($prepareGroupRoleData);
            }

            Db::commit();
            return retJson(Lang::POSTDone);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function putRBACGroup()
    {

        $params      = self::getParam([
            'group_id',
            'group_name',
            'role_ids',
        ]);
        (new RCBCValidate())->goCheck(__FUNCTION__, $params);
        $ids = explode(',', $params['role_ids']);
        $ids = array_filter($ids);

        Db::startTrans();
        try {
            $groupModel = GroupModel::where('id', $params['group_id'])->find();
            if (!$groupModel) {
                throw new NotFoundException();
            }
            $groupModel->name = $params['group_name'];
            $groupModel->save();

            (new GroupRoleModel())->where('group_id', $params['group_id'])->delete();

            if ($ids) {
                $prepareGroupRoleData = [];
                foreach ($ids as $id) {
                    $prepareGroupRoleData[] = [
                        'group_id' => $groupModel->id,
                        'role_id'  => $id,
                    ];
                }
                (new GroupRoleModel())->saveAll($prepareGroupRoleData);
            }

            Db::commit();
            return retJson(Lang::PUTDone);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function deleteRBACGroup()
    {

        $params      = self::getParam(['group_id']);
        (new RCBCValidate())->goCheck(__FUNCTION__, $params);

        Db::startTrans();
        try {
            $groupModel = GroupModel::where('id', $params['group_id'])->find();
            if (!$groupModel) {
                throw new NotFoundException();
            }
            //有用户残留
            $usersCount = UserModel::where('group_id', $params['group_id'])->count();
            if ($usersCount !== 0) {
                throw new RuntimeException(['msg' => '还有用户正处于此组，不可删除']);
            }

            //有group_role残留
            //$groupRoleCount = GroupRoleModel::where('group_id', $params['group_id'])->count();
            //if ($groupRoleCount !== 0) {
            //    throw new RuntimeException(['msg' => '请删除用户组权限表中的数据，再进行删除']);
            //}
            (new GroupRoleModel())->where('group_id', $params['group_id'])->update(['delete_time' => NOW_TIME]);
            $groupModel->delete();

            Db::commit();
            WarmUpCache::group();
            return retJson(Lang::DELETEDone);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function getRBACRoleList()
    {

        $data        = RbacService::getRBACRole();
        $ids         = [];
        $menu        = [
            [
                'id'   => 0,
                'name' => '根菜单',
                'pid'  => 0,
            ],
        ];
        foreach ($data as $item) {
            $ids[] = $item['id'];
            if ($item['is_menu'] === '是') {
                $menu[] = $item;
            }
        }
        $result = [
            'tree'    => getPidParent($data, 0),
            'ids'     => $ids,
            'default' => $data,
            'menu'    => $menu,
        ];
        return retJson(Lang::GETDone, $result);
    }

    /**
     * @return \think\response\Json
     * @throws \Exception
     */
    public function postRBACRole()
    {

        $params      = self::getParam([
            'role_name',
            'role_app',
            'role_controller',
            'role_action',
            'role_method',
            'role_is_menu',
            'role_common',
            'role_index',
            'role_pid',
        ]);
        (new RCBCValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $oldRoleModel = (new RoleModel())->where('name', $params['role_name'])->find();
            if ($oldRoleModel) {
                throw new ParameterFailedException(['msg' => '已存在该名称的权限']);
            }
            if ($params['role_pid'] !== 0) {
                $oldRoleModel = (new RoleModel())->where('id', $params['role_pid'])->find();
                if (!$oldRoleModel) {
                    throw new ParameterFailedException(['msg' => '该父级不存在']);
                }
            }

            $roleModel             = new RoleModel();
            $roleModel->name       = $params['role_name'];
            $roleModel->app        = $params['role_app'];
            $roleModel->controller = $params['role_controller'];
            $roleModel->action     = $params['role_action'];
            $roleModel->method     = $params['role_method'];
            $roleModel->is_menu    = $params['role_is_menu'];
            $roleModel->common     = $params['role_common'];
            $roleModel->index      = $params['role_index'];
            $roleModel->pid        = $params['role_pid'];
            $roleModel->save();

            Db::commit();
            return retJson(Lang::POSTDone);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function putRBACRole()
    {

        $params      = self::getParam([
            'role_id',
            'role_name',
            'role_app',
            'role_controller',
            'role_action',
            'role_method',
            'role_is_menu',
            'role_common',
            'role_index',
            'role_pid',
        ]);
        (new RCBCValidate())->goCheck(__FUNCTION__, $params);
        Db::startTrans();
        try {
            $roleModel = RoleModel::where('id', $params['role_id'])->find();
            if (!$roleModel) {
                throw new NotFoundException();
            }
            $roleModel->name       = $params['role_name'];
            $roleModel->app        = $params['role_app'];
            $roleModel->controller = $params['role_controller'];
            $roleModel->action     = $params['role_action'];
            $roleModel->method     = $params['role_method'];
            $roleModel->is_menu    = $params['role_is_menu'];
            $roleModel->common     = $params['role_common'];
            $roleModel->index      = $params['role_index'];
            $roleModel->pid        = $params['role_pid'];
            $roleModel->save();

            Db::commit();
            return retJson(Lang::PUTDone);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function deleteRBACRole()
    {

        $params      = self::getParam(['role_id']);
        (new RCBCValidate())->goCheck(__FUNCTION__, $params);

        Db::startTrans();
        try {
            $roleModel = RoleModel::where('id', $params['role_id'])->find();
            if (!$roleModel) {
                throw new NotFoundException();
            }
            //有grouprole残留
            $groupRoleModel = GroupRoleModel::where('role_id', $params['role_id'])->find();
            if ($groupRoleModel) {
                throw new RuntimeException(['msg' => '该权限被用户组占用，不可删除']);
            }

            $roleModel->delete_time = NOW_TIME;
            $roleModel->save();

            Db::commit();
            return retJson(Lang::DELETEDone);
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw $e;
        }
    }

    public function postRBACGroupRole()
    {

    }
}